#include  "SYSCFG.h";
#include  "FT60F21X.h";
#include  "include.h";
//#include  <math.h>;

/*
功能说明:
MCU第4脚接灯, 低电平点亮。第3脚接按键, 内部上拉。
上电灯不亮，
(1)第1次按键, 灯高亮, 亮度100%
(2)第2次按键，灯低亮，亮度25%
(3)第3次按键，灯进入呼吸状态, 亮度由0%到100%再到0%循环, 一个呼吸周期为3秒
(4)第4次按键, 灯闪烁
(5)第5次按键，灯双闪循环
(6)再按按键唤醒休眠, 点亮灯, 依次循环
开灯一分钟后自动关灯休眠
2025-04-13

KEY_IN ==> PA2 (第3脚)
LED    ==> PA4 (第4脚) => P1B0(PWM2)

*/

//===========================================================
//变量声明
//===========================================================

typedef enum {
    MODE_OFF = 0,
    MODE_HIGH = 1,
    MODE_LOW = 2,
    MODE_BREATH = 3,
    MODE_BLINK = 4,
    MODE_DOUBLE_BLINK = 5
} LedMode;

bit b_keyDown;
bit b_work;
bit F_led_s;
bit d_1ms;
bit F_led_ds;
bit b_hold;
bit b_dir;


unsigned char time50us;
unsigned char keyTick;
unsigned char keyUpTick;
unsigned char ledTick;
unsigned char sleepTick;
LedMode ledMode;
unsigned char duty;
unsigned char tm0Cnt;
unsigned char led_count;

unsigned int  minuteTimer;  // 优化为16位变量
unsigned int  blinkTimer;   // 闪烁计时器
unsigned char blinkState;   // 闪烁状态

//===========================================================
//常数
//===========================================================
#define  CONST_TMR0     165  //0XFF-100+1 (Timer0计数初值, 实测微调)
#define  CONST_PA       0x01 //PA0=1

#define  CONST_LOAD     100
#define  DUTY100        100  //100%亮度
#define  DUTY70         70   //70%亮度
#define  DUTY25         25   //25%亮度

#define  BREATH_CYCLE   3000 // 呼吸周期3秒(3000ms)
#define  BLINK_RATE     500  // 闪烁频率500ms
#define  DOUBLE_BLINK_RATE 250 // 双闪频率250ms
#define  DOUBLE_BLINK_PAUSE 750 // 双闪间隔750ms

#define  SLEEP_TIMEOUT  30   // 30ms后进入休眠

//===========================================================
//函数声明
//===========================================================

void Key_Scan(void);
void System_Sleep(void);
void LED_Control(void);
void Delay_Off(void);
void led_s(void);
void led_2s(void);

/*-----------------------------------------------------------
 * 函数名： interrupt ISR
 * 功能：  中断处理, 中断周期50us
 -----------------------------------------------------------*/
void interrupt ISR(void)
{
    if(INTCON & 0x04)           //Timer0中断标记 Bit[2]:T0IF
    {
        INTCON &= ~(1<<2);      //T0IF = 0;
        TMR0 = CONST_TMR0;      //计数初值

        time50us++;
        
        if(time50us >= 20)      // 20*50us = 1ms
        {
            time50us = 0;
            keyTick++;          // 1ms计数器
            ledTick++;
            blinkTimer++;
            minuteTimer++;
            sleepTick++;
            d_1ms = 1;
            led_count++; 
        }
        
        if(b_work)
        {
            tm0Cnt++;
            if(tm0Cnt >= CONST_LOAD)  // 模拟PWM频率= (1/50us)/CONST_LOAD=20KHz/100=200Hz
            {
                tm0Cnt = 0;
            }
            if(tm0Cnt < duty)  // 模拟PWM
            {
                LED = 0;  // 低电平点亮
            }
            else
            {
                LED = 1;
            }
        }
    }
}

/*-----------------------------------------------------------
 初始化设置定时器
 中断周期 = (256-100)*4T*2分频/16MHz = 50us
 -----------------------------------------------------------*/

void TIMER0_INITIAL (void)
{
    T0ON = 0;
    TMR0 = CONST_TMR0;      //计数初值
    T0CON0 = 0B00000000;    //Bit3 定时器0使能位 Bit[1:0]定时器时钟源选择位 00:指令周期 01:HIRC
    OPTION = 0B00000000;    //Bit[2:0]: PS 8个预分频比, 000=2分频
    T0ON = 1;
}

/*-----------------------------------------------------------
 上电系统初始化
 -----------------------------------------------------------*/

void POWER_INITIAL (void)
{
    OSCCON = 0B01110001;    //16MHz 1:1
    INTCON = 0;             //暂禁止所有中断
    TRISA = 1<<2;           //1:输入 0:输出.  PA2为输入模式 PA4输出模式
    PSRCA = 0;              //00:4mA    01/10:8mA   11:28mA bit[3:2]控制PA5源电流   bit[1:0]控制PA4源电流
    PSINKA = 0;             //bit[1:0]  控制PA5和PA4 0:灌电流最小 1:灌电流最大
    PORTA = CONST_PA;       //1:PAx输出高电平   0:PAx输出低电平 PA4输出高电平
    WPUA = 1<<2;            //1:使能PA2口上拉   0:关闭PA口上拉  PA2 上拉
}


/*-----------------------------------------------------------
 看门狗初始化
 wdt溢出时间 = (1/32000)*16位预分频值*8位预分频值
             = (1/32kHz)*1024*1 = 32ms
 -----------------------------------------------------------*/

void WDT_INITIAL (void)
{
    CLRWDT();                   //清看门狗
    WDTCON = (0X05<<1) | (1<<0);
    //Bit5:     0:LIRC 1:HIRC
    //Bit[4:1]: 0X05 1:1024
    //Bit0:     1:使能 WDT
}

/*-----------------------------------------------------------
 关灯
 -----------------------------------------------------------*/

void LED_Off(void)
{
    ledMode = MODE_OFF;
    b_work = 0;
    LED = 1;
}

/*-----------------------------------------------------------
 按键检测, 按键设为输入上拉, 按下后变为低电平
 -----------------------------------------------------------*/

void Key_Scan(void)
{    
    keyUpTick++;
    if(KEY_IN == 0)  //按键按下
    {
        keyUpTick = 0;
        sleepTick = 0;  //用于休眠唤醒
        
        if(b_keyDown == 0)
        {            
            b_keyDown = 1;  //按键按下标志

            if(keyTick >= 20)  // 消抖处理
            {
                keyTick = 0;
                
                // 循环切换LED模式
                ledMode = (LedMode)((ledMode + 1) % 6);
                
                switch(ledMode)
                {
                    case MODE_HIGH:     // 点亮LED, 亮度100%
                        b_work = 1;
                        duty = DUTY100;
                        minuteTimer = 0;  // 重置一分钟计时器
                        break;

                    case MODE_LOW:      // LED亮度25%
                        duty = DUTY25;
                        minuteTimer = 0;
                        break;

                    case MODE_BREATH:   // LED呼吸
                        blinkTimer = 0;
                        minuteTimer = 0;
						b_hold = 0;
						b_dir = 0;
                        break;
                        
                    case MODE_BLINK:    // LED闪烁
                        blinkTimer = 0;
                        blinkState = 0;
                        minuteTimer = 0;
                        break;
                        
                    case MODE_DOUBLE_BLINK:  // LED双闪
                        blinkTimer = 0;
                        blinkState = 0;
                        minuteTimer = 0;
                        break;
                        
                    case MODE_OFF:      // 关灯
                    default:
                        LED_Off();
                        break;
                }
            }
        }
    }
    else  //按键抬起
    {
		if(b_keyDown == 1)
        {
			keyTick = 0;
            sleepTick = 0;       //用于休眠唤醒
            if(keyUpTick >= 100)  //按键抬起消抖
            {
                b_keyDown = 0;
            }
        }
    }
}

#define  CONST_SPD      14   //呼吸速度, 时间单位1ms
#define  CONST_T2       200 

void LED_Breath(void)
{
    if(b_hold == 0)
    {
        if(ledTick >= CONST_SPD)
        {
            ledTick = 0;

            if(b_dir == 0)  //亮度增加
            {
                duty++;
                if(duty >= DUTY100)
                {
                    b_dir = 1;
                    b_hold = 1;
                }
            }
            else            //亮度减小
            {
                duty--;
                if(duty == 0)
                {
                    b_dir = 0;
                    b_hold = 1;
                }
            }
        }
    }
    else  //在最大和最小亮度时停顿200ms
    {
        if(ledTick >= CONST_T2)
        {
            ledTick = 0;
            b_hold = 0;
        }
    }
}

/*-----------------------------------------------------------
 LED控制 - 处理所有LED模式
 -----------------------------------------------------------*/
void LED_Control(void)
{
    if(!b_work) return;
    
    switch(ledMode)
    {
        case MODE_HIGH:
        case MODE_LOW:
            // 固定亮度模式，无需额外处理
            break;
            
        case MODE_BREATH:
            // 优化的呼吸灯算法 - 使用正弦波模拟更自然的呼吸效果
            {
				LED_Breath();
				/*
                // 计算当前呼吸位置 (0-2999)
                unsigned int breathPos = blinkTimer % BREATH_CYCLE;
                
                // 将位置映射到0-100的占空比值
                if(breathPos < BREATH_CYCLE / 2)
                {
                    // 亮度增加阶段
                    duty = (breathPos * 2 * DUTY100) / BREATH_CYCLE;
                }
                else
                {
                    // 亮度减少阶段
                    duty = DUTY100 - ((breathPos - BREATH_CYCLE / 2) * 2 * DUTY100) / BREATH_CYCLE;
                }*/
            }
            break;
            
        case MODE_BLINK:
            // 简单闪烁
            if(blinkTimer >= BLINK_RATE)//500
            {
                blinkTimer = 0;
				if(duty == 0)
				{
					duty = DUTY100;
				}
				else
				{
					duty = 0;
				}
                //duty = (duty == 0) ? DUTY100 : 0;
            }
            break;
            
        case MODE_DOUBLE_BLINK:
            // 双闪模式
            if(blinkTimer < DOUBLE_BLINK_RATE)
            {
                duty = DUTY100; // 第一次闪烁
            }
            else if(blinkTimer < DOUBLE_BLINK_RATE * 2)
            {
                duty = 0;
            }
            else if(blinkTimer < DOUBLE_BLINK_RATE * 3)
            {
                duty = DUTY100; // 第二次闪烁
            }
            else if(blinkTimer < DOUBLE_BLINK_RATE * 3 + DOUBLE_BLINK_PAUSE)
            {
                duty = 0;
            }
            else
            {
                blinkTimer = 0; // 重置计时器
            }
            break;
            
        default:
            break;
    }
}

/*-----------------------------------------------------------
 开灯后一分钟后关灯
 -----------------------------------------------------------*/

void Delay_Off(void)
{
    if(minuteTimer >= 60000)  // 60000ms = 1分钟
    {
        LED_Off();  // 关灯
    }
}

/*-----------------------------------------------------------
 主函数
 -----------------------------------------------------------*/

void main()
{
    POWER_INITIAL();        //系统初始化
    TIMER0_INITIAL();
    WDT_INITIAL();
    T0IE = 1;               //开定时器/计数器0中断
    GIE = 1;                //开中断

    ledMode = MODE_OFF;     // 初始为关灯状态
    
    while(1)
    {
        CLRWDT();           // 喂狗
        Key_Scan();         // 按键检测
        
        if(b_work)
        {
            LED_Control();  // 控制LED模式
            Delay_Off();    // 计时一分钟关灯
        }
        else
        {
            if(sleepTick >= SLEEP_TIMEOUT)  // 延时进入休眠
            {
                System_Sleep();
            }
        }
    }
}

/*-----------------------------------------------------------
 休眠
 -----------------------------------------------------------*/

void System_Sleep(void)
{
    SWDTEN = 0;         //关看门狗  //WDTCON = 0xE8;
    val = PORTA;        //清PA电平变化中断
    PAIF = 0;           //清 PA 端口变化总中断标志位
    IOCA = 0x04;        //使能 PA2 端口变化中断
    INTCON = 0x08;      //关总中断, 使能 PORTA 端口变化总中断(非外设中断)
    PORTA = CONST_PA;   //休眠前设置 I/O 口

    NOP();
    NOP();
    SLEEP();            //休眠
    NOP();
    NOP();

    PAIF = 0;           //清 PA 端口变化总中断标志位
    IOCA = 0x00;
    SWDTEN = 1;         //使能看门狗
    INTCON = 0xA0;      //开总中断, Timer0 溢出中断
    sleepTick = 0;
    
    // 唤醒后恢复状态
    if(ledMode != MODE_OFF)
    {
        b_work = 1;
    }
}    